<?php
namespace app\api\services;

use app\api\cache\ShopCache;
use app\api\consDir\OrderPrefixConst;
use app\api\consDir\SandConst;
use app\common\libs\Singleton;
use app\common\models\Order\Order;
use app\common\models\Order\OrderGoods;
use app\common\models\Order\OrderShop;
use app\common\models\Shop\Goods;
use app\common\models\Shop\Shop;
use app\common\models\Shop\ShopComment;
use app\common\models\Shop\ShopPic;
use Exception;
use think\Collection;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;
use think\facade\Log;

class ShopService
{
    use Singleton;

    public function shopGoodsCount($shopId): int
    {
        $where = [
            ['shop_id', '=', $shopId],
            ['status', '=', 1],
            ['deleted', '=', 0],
        ];
        return Goods::getInstance()->where($where)->count('id');
    }

    /**
     * @param $shopId
     * @param $page
     * @param $pageSize
     * @return array
     */
    public function shopPic($shopId, $page, $pageSize): array
    {
        $list = ShopPic::getInstance()
            ->where(['shop_id' => $shopId])
            ->limit(($page - 1) * $pageSize, $pageSize)
            ->order('sort asc')
            ->column('imgs');
        $list = empty($list) ? [] : $list;
        $arr  = [];
        foreach ($list as $k => $val) {
            if (empty($val)) {
                continue;
            }
            $imgList = explode(',', $val);
            if ($k == 0) {
                $arr = $imgList;
            } else {
                if ( ! empty($imgList)) {
                    $arr = array_merge($arr, $imgList);
                }
            }
        }

        return $arr;
    }

    public function shopListByIds($ids, $field = '*'): array
    {
        $where = [
            ['status', '=', 1],
            ['id', 'in', $ids],
        ];
        return Shop::getInstance()->where($where)->field($field)->column($field, 'id');
    }

    public function getComment($shopId, $isImg, $isBad, $page, $pageSize)
    {
        $where = [
            ['shop_id', '=', $shopId],
        ];
        if ( ! empty($isImg)) {
            $where[] = ['is_img', '=', 1];
        }
        if ( ! empty($isBad)) {
            $where[] = ['is_bad', '=', 1];
        }
        $shopComment = ShopComment::getInstance()
            ->where($where)
            ->field('serve_score ,environment_score,cost_score,all_score,is_img ,is_bad ,content,img_content,user_id,is_anonymity,create_at')
            ->limit(($page - 1) * $pageSize, $pageSize)
            ->order('create_at desc')
            ->select();

        foreach ($shopComment as &$val) {
            $user = MemberService::getInstance()->getUserInfo($val['user_id']);
            if (empty($user)) {
                unset($val);
                continue;
            }
            $user['userName']  = mb_substr($user['userName'], 0, 1) . '**';
            $val['userInfo']   = $user;
            //$val['imgContent'] = explode(',', $val['imgContent']);
            $val['imgContent'] = !empty($val['imgContent']) ? json_decode($val['imgContent'],true) : $val['imgContent'];
        }
        return $shopComment;
    }

    public function shopInfo($shopId, $field = ''): array
    {
        $where = [
            ['id', '=', $shopId],
        ];
        if (empty($field)) {
            $field = 'user_id ,city as send_city,create_at ,content,shop_banner,id,shop_logo,shop_name,per,address,latitude,longitude,shop_phone,goods_count,shop_type,freight_insurance,serve_score,environment_score,cost_score,all_score ,shop_business_img,open_week,
open_time_start,open_time_end,open_status,is_shop,is_box,is_battery,kf_phone';
        }
        $info = Shop::getInstance()->where($where)->field($field)->find();
        return empty($info) ? [] : $info->toArray();
    }

    public function shopInfoAll($shopId)
    {
        $where = [
            ['id', '=', $shopId],
        ];
        $info = Shop::getInstance()->where($where)->find();
        return empty($info) ? [] : $info->toArray();
    }

    /**
     * @param $shopType
     * @param $page
     * @param $pageSize
     * @param $lat
     * @param $lng
     * @param $order
     * @param $keyword
     * @param $categoryId
     * @param $city
     * @param $isHot
     * @param $isBrand
     * @param $isVillage
     * @param $minPer
     * @param $maxPer
     * @param $isWifi
     * @param $isStop
     * @param $isBox
     * @param $isBattery
     * @param $km
     * @return Collection
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function shopList($shopType, $page, $pageSize, $lat, $lng, $order, $keyword, $categoryId, $city, $isHot, $isBrand, $isVillage, $minPer, $maxPer, $isWifi, $isStop, $isBox, $isBattery, $km, $ids = [])
    {
        // arr 原始顺序不能随意调整了
        $arr = [
            'sort desc', // 0 综合排序
            'per desc', // 1 人均从高到低
            'per asc', // 2 人均从低到高
            'is_hot desc', // 3 热门
            'km asc', // 4 离我最近
            'sales desc', // 5 人气优先
            'all_score desc', // 6
        ];
        $where = [
            ['status', '=', 1],
            ['deleted', '=', 0],
        ];
        if ( ! empty($keyword)) {
            $where[] = ['shop_name', 'like', '%' . $keyword . '%'];
        }

        if ($isHot != null) {
            $where[] = ['is_hot', '>=', (int) $isHot];
        }
        if ($isBrand != null) {
            $where[] = ['is_brand', '=', (int) $isBrand];
        }
        if ($isWifi != null) {
            $where[] = ['is_wifi', '=', (int) $isWifi];
        }
        if ($isStop != null) {
            $where[] = ['is_shop', '=', (int) $isStop];
        }
        if ($isBox != null) {
            $where[] = ['is_box', '=', (int) $isBox];
        }
        if ($isBattery != null) {
            $where[] = ['is_battery', '=', (int) $isBattery];
        }

        if ($isVillage != null) {
            $where[] = ['is_village', '=', (int) $isVillage];
        }

        if ( ! empty($categoryId)) {
            $where[] = ['category_id', '=', $categoryId];
        }
        if ( ! empty($city)) {
            $where[] = ['city', 'like', '%' . $city . '%'];
        }
        if ($minPer != null) {
            $where[] = ['per', '>=', (int) $minPer];
        }
        if ($maxPer) {
            $where[] = ['per', '<', $maxPer];
        }

        if ( ! empty($ids)) {
            $where[] = ['id', 'in', $ids];
        }

        switch ($shopType) {
            //1线下 2线上 3都有
            case 1:
                $where[] = ['shop_type', 'in', [1, 3]];
                $juli    = "ROUND(
        6378.138 * 2 * ASIN(
            SQRT(
                POW(
                    SIN(
                        (
                            " . $lat . " * PI() / 180 - latitude * PI() / 180
                        ) / 2
                    ),
                    2
                ) + COS(" . $lat . " * PI() / 180) * COS(latitude * PI() / 180) * POW(
                    SIN(
                        (
                            " . $lng . " * PI() / 180 - longitude * PI() / 180
                        ) / 2
                    ),
                    2
                )
            )
        ) * 1000
    )";
                $field = 'id,shop_logo,shop_name,per,all_score,address,latitude,longitude,' . $juli . '  AS km';
                if ( ! empty($km)) {
                    $order   = 4;
                    $where[] = [\think\facade\Db::raw($juli), '<=', (int) $km];
                }
                $list = Shop::getInstance()
                    ->where($where)
                    ->field($field)
                    ->limit(($page - 1) * $pageSize, $pageSize)
                    ->order($arr[$order] ?? $arr[0])
                    ->order('km asc')
                    ->select();
                foreach ($list as $k => &$val) {
                    $val['km'] = $val['km'] / 1000;
                    /*if ($km > 0 && $km < $val['km']) {
                        unset($list[$k]);
                    }*/
                }
                // echo Shop::getInstance()->getLastSql();exit;
                break;
            default:
                $where[] = ['shop_type', 'in', [2, 3]];
                $field   = 'id,shop_logo,shop_name,goods_count';
                $list    = Shop::getInstance()
                    ->where($where)
                    ->field($field)
                    ->limit(($page - 1) * $pageSize, $pageSize)
                    ->order($arr[$order] ?? $arr[0])
                    ->order('km asc')
                    ->select();
                foreach ($list as &$val) {
                    $val['goodsList'] = GoodsService::getInstance()
                        ->goodsInfo($val['id'], 1, 3, 1, 0, '', 0, 'id,goods_title,goods_img,sell_price');
                }
                break;
        }
        return $list;
    }

    public function getShopInfoById($shopId, string $field = 'id,shop_name,user_id,status,gxz_rate'): array
    {
        $shopData = Shop::getInstance()->where('id', '=', $shopId)->field($field)->find();
        if (empty($shopData)) {
            return [];
        }
        return $shopData->toArray();
    }

    /**
     * 店铺信息
     * @param $userId
     * @param string $field
     * @return array
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function getShopInfo($userId, string $field = 'id,shop_name,status,auth_remark'): array
    {
        // $userId = 1000031;
        $shopData = \app\common\models\Shop\ShopApply::getInstance()
            ->where('user_id', '=', $userId)
            ->field($field)
            ->find();
        if (empty($shopData)) {
            return [];
        }
        $data                 = $shopData->toArray();
        $data['marks']        = empty($data['marks']) ? [] : str2arr($data['marks']);
        $data['openWeek']     = empty($data['openWeek']) ? [] : json_decode($data['openWeek'], true);
        $data['bankCardInfo'] = empty($data['bankCardInfo']) ? null : json_decode($data['bankCardInfo'], true);

        return $data;
    }

    public function insertShop($data)
    {
        return Shop::getInstance()->insert($data);
    }

    /**
     * 更新店铺信息
     * @param $id
     * @param $data
     */
    public function updateUser($id, $data, $userID = 0)
    {
        Shop::getInstance()->update($data, ['id' => $id]);
        //更新缓存
        $field = 'id,shop_name,status';
        ShopCache::setShopInfo($userID . $field, $data);
    }

    /**
     * @throws ModelNotFoundException
     * @throws DataNotFoundException
     * @throws DbException
     */
    public function shopComment($shopId, $serveScore, $environmentScore, $costScore): bool
    {
        $field = 'serve_score,environment_score,cost_score,all_score';
        $shop  = Shop::getInstance()
            ->where('id', $shopId)
            ->field($field)
            ->find();
        if ( ! empty($shopComment)) {
            return false;
        }
        $serveScore              = bcmul($shop['serveScore'] + $serveScore, 0.5, 1);
        $environmentScore        = bcmul($shop['environmentScore'] + $environmentScore, 0.5, 1);
        $costScore               = bcmul($shop['costScore'] + $costScore, 0.5, 1);
        $allScore                = bcmul($shop['allScore'] + (($serveScore + $environmentScore + $costScore) / 3), 0.5, 1);
        $shop->serve_score       = $serveScore;
        $shop->environment_score = $environmentScore;
        $shop->cost_score        = $costScore;
        $shop->all_score         = $allScore;
        $shop->save();
        return true;
    }

    /**
     * 商家让利>=平台总优惠+折扣优惠 直接分
     * 返回值扣除商家的钱>=0 直接分，否则平台收
     * @throws DataNotFoundException
     * @throws ModelNotFoundException
     * @throws DbException
     */
    public function IsDirectByOrderNo($orderNo)
    {
        $where = [
            'order_no' => $orderNo,
        ];
        $orderData = Order::getInstance()->where($where)->find();
        //4供应链
        if ($orderData['order_type'] == 4) {
            return -1;
        }
        //线上单
        $orderShops = OrderShop::getInstance()->where($where)->select();
        $totalShopFee = 0;
        foreach($orderShops as $v){
            $platformFee = Shop::getInstance()->where('id',$v['shop_id'])->value('platform_fee');
            $v['sellPrice'] = $v['sellPrice'] > 0 ? $v['sellPrice'] : $v['payPrice'];
            $totalShopFee = bcadd($totalShopFee,bcmul($v['sellPrice'],$platformFee*0.01,2),2);
        }
        //商家让利>=(平台总优惠+商家优惠+折扣优惠) 直接分
        $orderShop = OrderShop::getInstance()->field('sum(platform_sale) total_platform_sale,sum(shop_sale) total_shop_sale,sum(discount_sale) total_discount_sale,sum(pay_price) total_pay_price')->where($where)->find();
        $totalPlatformSale = $orderShop['totalPlatformSale'] ?? 0;
        $totalDiscountSale = $orderShop['totalDiscountSale'] ?? 0;
        $totalShopSale = $orderShop['total_shop_sale'] ?? 0;
        $totalPayPrice = $orderShop['total_pay_price'] ?? 0;
        if($totalShopFee >= bcadd($totalPlatformSale,$totalDiscountSale,2)){
            //让给平台的钱 = 商家让利比例金额-平台优惠券-平台折扣
            return bcsub(bcsub($totalShopFee,$totalPlatformSale,2),$totalDiscountSale,2);
        }
        return -1;
    }

    /**
     * @throws Exception
     */
    public function payToShopSand($orderNo, $payNo, $isDirect, $payPrice, $goodsMoney, $shopUserId, $payType, $msg): bool
    {
        if($payType == 4){
            //$msg = '商家收入，商品订单'.$orderNo;
            if($isDirect){
                //用户支付后需要杉德确认转账
                Log::info($orderNo . '商家杉德确认转账金额' . $goodsMoney);
                //$amount = env('test.is_test') ? 0.01 : $goodsMoney;
                $ret = SandService::getInstance()->transferConfirm(getNo(OrderPrefixConst::TC), $payNo, $payPrice, 'confirm', SandConst::PREFIX . $shopUserId);
                Log::info($orderNo . '线下商家杉德确认转账返回' . json_encode($ret, 256));
                if (!isset($ret['resultStatus']) || $ret['resultStatus'] != 'success') {
                    throw new Exception($orderNo . $ret['errorDesc']);
                }
            }else{
                Log::info($orderNo . '平台转账给商家杉德金额' . $goodsMoney);
                //$amount = env('test.is_test') ? 0.01 : $goodsMoney;
                $ret = SandService::getInstance()->transfer($goodsMoney, env('sand.consumeMid'), SandConst::PREFIX . $shopUserId, 0, getNo(OrderPrefixConst::TR),'rt',$msg);
                if (!isset($ret['code']) || $ret['code'] != 1) {
                    throw new Exception($orderNo . $ret['data']);
                }
            }
        }else{
            Log::info($orderNo . '余额支付平台转账给商家杉德金额' . $goodsMoney);
            //$amount = env('test.is_test') ? 0.01 : $goodsMoney;
            $ret = SandService::getInstance()->transfer($goodsMoney, env('sand.consumeMid'), SandConst::PREFIX . $shopUserId, 0, getNo(OrderPrefixConst::TR),'rt',$msg);
            if (!isset($ret['code']) || $ret['code'] != 1) {
                throw new Exception($orderNo . $ret['data']);
            }
        }
        return true;
    }
}
